package projeto.lp2.grupo6.testes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.junit.*;

import projeto.lp2.grupo6.logica.Estabelecimento;
import projeto.lp2.grupo6.logica.Opiniao;
import projeto.lp2.grupo6.logica.TipoDeAlmocoServido;
import projeto.lp2.grupo6.logica.Usuario;

/**
 * Aluno: 
 *      Guilherme Monteiro
 *      Italo Guedes
 *      Tiago Leite
 * 
 * @author guilhermemg
 * @author tiagoln
 * @author italogas
 *
 */
public class UsuarioTest {

    Usuario u1;
    Usuario u2;

    @Before
    public void setup() throws Exception {
        try {
            String nome1 = "";
            String nome2 = "Joao";
            u1 = new Usuario(nome1);
            u2 = new Usuario(nome2);
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em usuarios criados corretamente");
        }
    }

    @Test(expected = Exception.class)
    public void testUsuario() throws Exception {
        String nome1 = "";
        @SuppressWarnings("unused")
        Usuario u1 = new Usuario(null);
        @SuppressWarnings("unused")
        Usuario u2 = new Usuario(nome1);
    }

    @Test
    public void testGetNome() {
        try {
            Assert.assertEquals(u1.getNome(), "");
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em getNome de u1");
        }
        try {
            Assert.assertEquals(u2.getNome(), "Joao");
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em getNome de u2");
        }
    }

    @Test(expected = Exception.class)
    public void testSetNome1() throws Exception {
        u1.setNome(null);
    }

    @Test
    public void testSetNome2() throws Exception {
        try {
            u1.setNome("");
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em setNome com nome vazio");
        }
    }

    @Test
    public void adicionaOpiniaoTest() {
        try {
            Estabelecimento e1 = new Estabelecimento("nome1", "endereco estabelecimento 1", TipoDeAlmocoServido.A_LA_CARTE);
            u1.adicionaOpiniao(e1, 5);
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em adiciona opiniao");
        }
        try {
            Estabelecimento e1 = new Estabelecimento("nome1", "endereco estabelecimento 1", TipoDeAlmocoServido.PRATO_FEITO);
            u1.adicionaOpiniao(e1, -6);
        } catch (Exception e) {
            Assert.assertEquals(e.getMessage(), "Nota invalida");
        }
    }

    @Test
    public void equalsTest() {
        try {
            Usuario u1 = new Usuario("nome1");
            Usuario u2 = null;
            Assert.assertTrue(u1.equals(u2));
            Assert.fail("Erro em equals de Usuario");
        } catch (Exception e) {
            Assert.assertEquals(e.getMessage(), "Erro em Usuario nulo.");
        }
        try {
            Usuario u1 = new Usuario("nome1");
            Usuario u2 = new Usuario("nome2");
            Assert.assertFalse(u1.equals(u2));
        } catch (Exception e) {
            Assert.fail("Erro em equals de Usuario");
        }
        try {
            Usuario u1 = new Usuario("nome1");
            Usuario u2 = new Usuario("nome1");
            Assert.assertTrue(u1.equals(u2));
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em equals de usuario");
        }
    }

    @Test(expected = Exception.class)
    public void testaSetListaDeOpinioes1() throws Exception {
        Usuario u1 = new Usuario("nome1");
        u1.setListaDeOpinioes(null);
    }

    @Test(expected = Exception.class)
    public void testaSetListaDeOpinioes2() throws Exception {
        Usuario u1 = new Usuario("nome1");
        List<Opiniao> listaOp = new ArrayList<Opiniao>();
        u1.setListaDeOpinioes(listaOp);
    }

    @Test(expected = Exception.class)
    public void testaSetListaDeOpinioes3() throws Exception {
        Usuario u1 = new Usuario("nome1");
        List<Opiniao> listaOp = new ArrayList<Opiniao>();
        Opiniao o1 = null;
        Opiniao o2 = null;
        listaOp.add(o1);
        listaOp.add(o2);
        u1.setListaDeOpinioes(listaOp);
    }

    @Test
    public void testaSetListaDeOpinioes4() throws Exception {
        try {
            Usuario u1 = new Usuario("Nome2");
            List<Opiniao> listaOpinioes = new ArrayList<Opiniao>();
            Estabelecimento e1 = new Estabelecimento("nome estab1", "rua 1", TipoDeAlmocoServido.A_LA_CARTE);
            Estabelecimento e2 = new Estabelecimento("nome estab2", "rua dois", TipoDeAlmocoServido.PRATO_FEITO);
            listaOpinioes.add(new Opiniao(e1, 1));
            listaOpinioes.add(new Opiniao(e2, 0));
            u1.setListaDeOpinioes(listaOpinioes);
        } catch (Exception e) {
            Assert.assertEquals("Erro em tamanho de lista de opinioes", e.getMessage());
        }
    }

    @Test
    public void testaSetListaDeOpinioes5() throws Exception {
        try {
            final int TAMANHO_LISTA_OPINIOES = 39;

            Usuario u1 = new Usuario("Nome2");
            List<Opiniao> listaOpinioes = new ArrayList<Opiniao>();
            Estabelecimento e1 = new Estabelecimento("nome estab1", "rua 1", TipoDeAlmocoServido.A_LA_CARTE);
            Estabelecimento e2 = new Estabelecimento("nome estab2", "rua dois", TipoDeAlmocoServido.PRATO_FEITO);

            final int estab1 = 0;
            final int estab2 = 1;

            Map<Integer, Integer> mapaNotasMaioresQue5 = new HashMap<Integer, Integer>();

            mapaNotasMaioresQue5.put(0, 0);
            mapaNotasMaioresQue5.put(1, 1);
            mapaNotasMaioresQue5.put(2, 2);
            mapaNotasMaioresQue5.put(3, 3);
            mapaNotasMaioresQue5.put(4, 4);
            mapaNotasMaioresQue5.put(5, 5);
            mapaNotasMaioresQue5.put(6, -1);
            mapaNotasMaioresQue5.put(7, -2);
            mapaNotasMaioresQue5.put(8, -3);
            mapaNotasMaioresQue5.put(9, -4);
            mapaNotasMaioresQue5.put(10, -5);

            final int quantEstab = 2;
            final int quantNotasPossiveis = 11;

            for (int i = 0; i < TAMANHO_LISTA_OPINIOES; i++) {
                Random ran = new Random();
                int estabEscolhido = ran.nextInt(quantEstab);
                int nota = ran.nextInt(quantNotasPossiveis);

                nota = mapaNotasMaioresQue5.get(nota);
                if (estabEscolhido == estab1) {
                    listaOpinioes.add(new Opiniao(e1, nota));
                } else if (estabEscolhido == estab2) {
                    listaOpinioes.add(new Opiniao(e2, nota));
                }
            }
            u1.setListaDeOpinioes(listaOpinioes);
        } catch (Exception e) {
            Assert.fail("Nao esperava erro em lista de opinioes criada corretamente");
        }
    }
}
